package com.xxl.job.executor.service.jobhandler;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.bizsys.domain.CreditAccount;
import com.ruoyi.bizsys.domain.LoanDeferredOrder;
import com.ruoyi.bizsys.domain.LoanIou;
import com.ruoyi.bizsys.domain.RepaymentOrder;
import com.ruoyi.bizsys.mapper.LoanDeferredOrderMapper;
import com.ruoyi.bizsys.service.ICreditAccountService;
import com.ruoyi.bizsys.service.ILoanIouService;
import com.ruoyi.bizsys.service.IRepaymentOrderService;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.bizsys.vo.MonnifyReservedAccount;
import com.ruoyi.business.component.RepaymentMqSendService;
import com.ruoyi.business.service.IBRepaymentService;
import com.ruoyi.business.service.ICustVaService;
import com.ruoyi.business.service.IDoRepaymentLastService;
import com.ruoyi.business.service.IRepaymentService;
import com.ruoyi.common.constant.LoanConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.extdata.common.config.PayStackConfig;
import com.ruoyi.extdata.service.IExternalApiService;
import com.ruoyi.sms.service.ISmsService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * 刷新扣款结果
 *
 * @author ruoyi
 */
@Slf4j
@Component
public class RepayTransferQueryJob {

    @Autowired
    IRepaymentOrderService repaymentOrderService;

    @Autowired
    IExternalApiService externalApiService;

    @Autowired
    PayStackConfig payStackConfig;

    @Autowired
    IRepaymentService repaymentService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    IBRepaymentService bRepaymentService;

    @Autowired
    RepaymentMqSendService repaymentMqService;

    @Autowired
    IDoRepaymentLastService doRepaymentLastService;

    @Autowired
    ICreditAccountService creditAccountService;

    @Autowired
    LoanDeferredOrderMapper loanDeferredOrderMapper;

    @Autowired
    ISmsService smsService;

    @Autowired
    ICustVaService custVaService;

    @Autowired
    ILoanIouService loanIouService;

    /**
     * 定时任务2分钟跑一次
     */
    @XxlJob("repayTransferQueryJobHandler")
    public void execute() {
        XxlJobHelper.log("还款交易轮询任务 Start >>>>>>>>>>");

        // 查询所有 Paystack 代扣还款中记录
        List<RepaymentOrder> repaymentOrderPendingList = repaymentOrderService.list(
                new QueryWrapper<RepaymentOrder>()
                        .select("id", "cust_no")
                        .in("action_type",
                                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERATE,
                                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_COLLECTION,
                                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERATEDEFER,
                                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERAT_WALLET_PAYSTACK,
                                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_PARTIAL_DEBITS_PAYSTACK,
                                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_DATE_BATCH)
                        .eq("repay_status", BizConstants.REPAYMENT_ORDER_STATUS_DOING)
                        .eq("state", BizConstants.BIZ_STATUS_1));

        if (CollectionUtils.isEmpty(repaymentOrderPendingList)) {
            XxlJobHelper.log("还款交易轮询任务 End >>>>>>>>>> 无待处理数据");
            return;
        }

        for (RepaymentOrder repaymentOrder : repaymentOrderPendingList) {
            String custNo = repaymentOrder.getCustNo();
            XxlJobHelper.log("开始查询客户号 {} 还款交易结果", custNo);

            String lockKey = LoanConstants.CUST_ACCOUNT_LOCK_KEY_PREFIX + custNo;
            RLock lock = redisCache.lock(lockKey);
            try {
                long start = System.currentTimeMillis();

                //再次查找repaymentOrder
                repaymentOrder = repaymentOrderService.getById(repaymentOrder.getId());
                if (repaymentOrder.getRepayStatus() != BizConstants.REPAYMENT_ORDER_STATUS_DOING) {
                    continue;
                }
//                // 如果是新卡还款操作，需要限制轮询次数和时间
//                if (StringUtils.equalsAny(repaymentOrder.getActionType(),
//                        BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERAT_CARD_STACK,
//                        BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERATEDEFER_CARD_STACk)) {
//                    // 新卡还款延期+还款all 创建时间+3小时内 < 当前时间 且 当前时间 - 创建时间 / 10 <18
//                    double leftHours = DateUtils.getDateDiff(5, new Date(), repaymentOrder.getCreateTime());
//                    if (leftHours > 3) {
//                        log.info(repaymentOrder.getRepaymentNo() + "超过3小时不轮询");
//                        continue;
//                    }
//                    //小于3小时内
//                    double passMinutes = DateUtils.getDateDiff(6, new Date(), repaymentOrder.getCreateTime());
//                    if (passMinutes / 10 > 18) {
//                        log.info(repaymentOrder.getRepaymentNo() + "超过18次小时不轮询");
//                        continue;
//                    }
//                }
                this.refreshRepayResult(repaymentOrder);

                log.info("锁占用时间，耗时：{} ms" + (System.currentTimeMillis() - start));
            } catch (Exception e) {
                bRepaymentService.saveRepaymentException(repaymentOrder.getRepaymentNo(), BizConstants.REPAYMENT_EXCEPTION_TYPE_PAYSTACK, repaymentOrder.getRepaymentAmt(), custNo);
                XxlJobHelper.log("客户号 {} 还款结果查询异常：", custNo);
                XxlJobHelper.log(e);
            } finally {
                lock.unlock();
            }
        }

        XxlJobHelper.log("还款交易轮询任务 End >>>>>>>>>>");
    }

    /**
     * 定时任务：新卡支付的，1小时查询1次3小时前的数据
     */
    @XxlJob("newCardRepayTransferQueryJobHandler")
    public void runBatchForNewCard(String flag) {
        log.info("新卡支付还款交易轮询任务 Start >>>>>>>>>>");

        //查询所有代扣未出结果的
        QueryWrapper<RepaymentOrder> queryWrapper = new QueryWrapper<RepaymentOrder>();
        queryWrapper.eq("repay_status", BizConstants.REPAYMENT_ORDER_STATUS_DOING);
        queryWrapper.eq("state", BizConstants.BIZ_STATUS_1);
        queryWrapper.in("action_type",
                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERAT_CARD_STACK,
                BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERATEDEFER_CARD_STACk);

        if (StringUtils.isBlank(flag)) {
            queryWrapper.lt("create_time", DateUtils.dateRollStr(3, LocalDateTime.now()));
        }
        List<RepaymentOrder> list = repaymentOrderService.list(queryWrapper);
        for (RepaymentOrder repaymentOrder : list) {
            log.info("repaymentOrder:{}", repaymentOrder.toString());
            String lockKey = LoanConstants.CUST_ACCOUNT_LOCK_KEY_PREFIX + repaymentOrder.getCustNo();
            RLock lock = redisCache.lock(lockKey);
            try {
                long start = System.currentTimeMillis();
                //再次查找repaymentOrder
                repaymentOrder = repaymentOrderService.selectRepaymentOrderById(repaymentOrder.getId());
                if (repaymentOrder.getRepayStatus() != BizConstants.REPAYMENT_ORDER_STATUS_DOING) {
                    continue;
                }
//                // 如果是新卡还款操作，需要限制轮询次数和时间
//                if (StringUtils.equalsAny(repaymentOrder.getActionType(),
//                        BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERAT_CARD_STACK,
//                        BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERATEDEFER_CARD_STACk)) {
//                    // 新卡还款延期+还款all 创建时间+3小时内 < 当前时间 且 当前时间 - 创建时间 / 10 <18
//                    double leftHours = DateUtils.getDateDiff(5, new Date(), repaymentOrder.getCreateTime());
//                    if (leftHours > 3) {
//                        log.info(repaymentOrder.getRepaymentNo() + "超过3小时不轮询");
//                        continue;
//                    }
//                    //小于3小时内
//                    double passMinutes = DateUtils.getDateDiff(6, new Date(), repaymentOrder.getCreateTime());
//                    if (passMinutes / 10 > 18) {
//                        log.info(repaymentOrder.getRepaymentNo() + "超过18次小时不轮询");
//                        continue;
//                    }
//                }
                this.refreshRepayResult(repaymentOrder);
                long end = System.currentTimeMillis();
                log.info("锁占用时间，耗时：" + (end - start) + " ms");
            } catch (Exception e) {
                bRepaymentService.saveRepaymentException(repaymentOrder.getRepaymentNo(), BizConstants.REPAYMENT_EXCEPTION_TYPE_PAYSTACK, repaymentOrder.getRepaymentAmt(), repaymentOrder.getCustNo());
            } finally {
                lock.unlock();
            }
        }
        log.info("新卡支付还款交易轮询任务 End >>>>>>>>>>");
    }


    private void refreshRepayResult(RepaymentOrder repaymentOrder) {
        try {
            JSONObject apiRes = externalApiService.invokePayStackApi("Verify-Transaction", payStackConfig.getVerifyTransaction().replace("REFERENCE", repaymentOrder.getPayTransSerialNo()), "GET", null, null);
            String transStatus = apiRes.getString("status");
            externalApiService.dealTransferData("charge." + transStatus, "query", repaymentOrder.getCustNo(), apiRes);

            //更新扣款申请状态
            repaymentOrder.setRemark(transStatus + "：" + apiRes.getString("gateway_response"));
            String reference = repaymentOrder.getPayTransSerialNo();
            if ("success".equals(transStatus)) {
                String redisKey = BizConstants.LOAN_REPAY_CARD + repaymentOrder.getLoanSerialNo();
                redisCache.deleteObject(redisKey);

                repaymentOrder.setPayTime(getPayTime(apiRes));
                repaymentOrderService.updateRepaymentOrder(repaymentOrder);

                // 判断|DF的标示进行发送到不同的mq进行处理
                // 正常还款无钱包-无延期购买
                if (reference.indexOf("-") == -1) {
                    repaymentMqService.syncSendMqRepayMentRefreshRepayResultJob(repaymentOrder, repaymentOrder.getCustNo());
                    return;
                }
                // 余额代扣
                if (reference.indexOf(BizConstants.PAY_TRANS_FLAG_CARD_WITHHOLD) != -1) {
                    repaymentMqService.cardBatchDebitRepayment(repaymentOrder, apiRes);
                    return;
                }

                //有钱包-正常全额还款
                if (reference.indexOf(BizConstants.PAY_TRANS_FLAG_PAY_ALL_WALLET) != -1) {
                    CreditAccount creditAccount = creditAccountService.getNormalAcountOnLoan(repaymentOrder.getCustNo());
                    if (null != creditAccount) {
                        repaymentMqService.selfWalletForBfenRepaymentMq(repaymentOrder, creditAccount.getId());
                    }
                    return;
                }

                //无钱包-有延期购买
                if (reference.indexOf(BizConstants.PAY_TRANS_FLAG_DF) != -1) {
                    CreditAccount creditAccount = creditAccountService.getNormalAcountOnLoan(repaymentOrder.getCustNo());
                    if (null != creditAccount) {
                        repaymentMqService.selfdeferRepaymentMq(repaymentOrder, creditAccount);
                    }
                    return;
                }

                // 场景 有钱包100-延期购买卡支付2900 共3000
                if (reference.indexOf(BizConstants.PAY_TRANS_FLAG_DF_WALLET) != -1) {
                    CreditAccount creditAccount = creditAccountService.getNormalAcountOnLoan(repaymentOrder.getCustNo());
                    if (null != creditAccount) {
                        repaymentMqService.selfdeferWalletForBfenRepaymentMq(repaymentOrder, creditAccount);
                    }
                    return;
                }

            } else {
//                if (!"pending".equals(transStatus) && !"timeout".equals(transStatus)) {
//                    repaymentOrder.setRepayStatus(BizConstants.REPAYMENT_ORDER_STATUS_FAIL);
//                }
                if ("failure".equals(transStatus) || "failed".equals(transStatus) || "abandoned".equals(transStatus)) {
                    repaymentOrder.setUpdateTime(new Date());
                    repaymentOrder.setRepayStatus(BizConstants.REPAYMENT_ORDER_STATUS_FAIL);
                    repaymentOrderService.updateById(repaymentOrder);

                    if (BizConstants.LOAN_REPAYMENT_ORDER_TYPE_PARTIAL_DEBITS_PAYSTACK.equals(repaymentOrder.getActionType())) {
                        // 余额代扣不发送失败短信
                        return;
                    }

                    // 更新延期订单
                    if (null != repaymentOrder.getLoanDeferOrderNo()) {
                        LoanDeferredOrder loanDeferredOrder = loanDeferredOrderMapper.selectByOrderNo(repaymentOrder.getLoanDeferOrderNo());
                        log.info(repaymentOrder.getLoanSerialNo() + "2分钟轮询：loanDeferredOrder:{}", loanDeferredOrder.toString());

                        loanDeferredOrder.setRemark(transStatus + "：" + apiRes.getString("gateway_response"));
                        loanDeferredOrder.setStatus(LoanDeferredOrder.STATUS_FAILED);
                        loanDeferredOrderMapper.updateById(loanDeferredOrder);

                        if (reference.indexOf(BizConstants.PAY_TRANS_FLAG_DF_WALLET) != -1) {
                            // 用了钱包需要解冻钱包更新失败
                            repaymentOrderService.updateRepayStatusToFaildByPayTransSerialNo(loanDeferredOrder.getWalletNo());
                            doRepaymentLastService.updateWalletOrderToFailed(loanDeferredOrder.getWalletNo(), true);
                        }

                        LoanIou loanIou = loanIouService.getLoanIouByLoanSerialNo(repaymentOrder.getLoanSerialNo());
                        String nowRepayDate = loanIou.getRepayDate();
                        MonnifyReservedAccount monnifyReservedAccount = custVaService.getVaReservedAccount(loanIou.getCustNo());
                        // 发送回调购买失败的短
                        smsService.sendDelayProductSms(loanIou, repaymentOrder, "failure", nowRepayDate, monnifyReservedAccount);
                    }

                    bRepaymentService.deferredWithholdingFail(repaymentOrder);
                }
            }
        } catch (BusinessException e) {
            log.error("refreshRepayResult 查询代扣交易结果异常：{}, {}", e.getCode(), e.getMessage());

            repaymentOrder.setRemark(e.getDetails());
            if (RspEnmu.TRANSACTION_SERIAL_NO_NOT_EXISTS.getCode().equals(e.getCode()) || RspEnmu.EXTERNAL_API_RSP_FALSE.getCode().equals(e.getCode())) {
                repaymentOrder.setRepayStatus(BizConstants.REPAYMENT_ORDER_STATUS_FAIL);
                // repaymentOrder.setPayTransSerialNo(null);
                repaymentOrderService.updateRepaymentOrder(repaymentOrder);
            }
            return;
        }

//        //更新状态
//        if (BizConstants.REPAYMENT_ORDER_STATUS_DOING != repaymentOrder.getRepayStatus()) {
//
//            // repaymentOrderService.updateRepaymentOrder(repaymentOrder);
//
//            //如果是手工代扣发送结果通知短信
////            if (BizConstants.LOAN_REPAYMENT_ORDER_TYPE_OPERATE.equals(repaymentOrder.getActionType())) {
////                //loanInfoService.sendRepaidResultSms(repaymentOrder);
////                if(BizConstants.REPAYMENT_ORDER_STATUS_SUCCESS == repaymentOrder.getRepayStatus()){
////                    iSendSmsService.activeRepayment(repaymentOrder,"success");
////                }else if(BizConstants.REPAYMENT_ORDER_STATUS_FAIL == repaymentOrder.getRepayStatus()){
////                    iSendSmsService.activeRepayment(repaymentOrder,"fail");
////                }
////            }
//
//            if (BizConstants.REPAYMENT_ORDER_STATUS_SUCCESS == repaymentOrder.getRepayStatus()) {
//                //执行延迟代扣逻辑
//                //ibRepaymentService.deferredWithholdingSuccess(repaymentOrder);
//            }else if(BizConstants.REPAYMENT_ORDER_STATUS_FAIL == repaymentOrder.getRepayStatus()){
//                ibRepaymentService.deferredWithholdingFail(repaymentOrder);
//            }
//        }
    }

    private static Date getPayTime(JSONObject debitResult) {
        try {
            String payTimeStr = StringUtils.getValue(debitResult, "paid_at");
            if (StringUtils.isBlank(payTimeStr)) {
                payTimeStr = StringUtils.getValue(debitResult, "transaction_date");
            }
            return DateUtils.parseUTCText(payTimeStr);
        } catch (Exception e) {
            log.warn("paidAt format error", e.getMessage());
            return new Date();
        }
    }

}